package com.springboot.template.service.impl;

import java.util.Date;
import java.util.List;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.springboot.template.domain.SecurityKeyInfo;
import com.springboot.template.domain.SecurityUser;
import com.springboot.template.mapper.SecurityKeyInfoMapper;
import com.springboot.template.mapper.SecurityUserMapper;
import com.springboot.template.service.ISecurityUserService;
import com.springboot.template.utils.CryptoUtils;
import com.springboot.template.utils.DateUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
/**
 * 用户Service业务层处理
 *
 * @author ruoyi
 * @date 2024-05-30
 */
@Service
public class SecurityUserServiceImpl implements ISecurityUserService
{
    @Autowired
    private SecurityUserMapper securityUserMapper;

    @Autowired
    private ISecurityUserService securityUserService;

    @Autowired
    private SecurityKeyInfoMapper securityKeyInfoMapper;

    /**
     * 查询用户
     *
     * @param id 用户主键
     * @return 用户
     */
    @Override
    public SecurityUser selectSecurityUserById(Long id)
    {
        return securityUserMapper.selectSecurityUserById(id);
    }

    /**
     * 查询用户列表
     *
     * @param securityUser 用户
     * @return 用户
     */
    @Override
    @Cacheable(value = {"securityUser"}, key="'channel:' + #securityUser.channel+':userId:' + #securityUser.userId", unless="#result.size()==0")
    public List<SecurityUser> selectSecurityUserList(SecurityUser securityUser)
    {
        return securityUserMapper.selectSecurityUserList(securityUser);
    }

    /**
     * 新增用户
     *
     * @param securityUser 用户
     * @return 结果
     */
    @Override
    public int insertSecurityUser(SecurityUser securityUser)
    {
        return securityUserMapper.insertSecurityUser(securityUser);
    }

    @Override
    public int verifySecurityUser(SecurityUser securityUser) {
        if (securityUser.getToken() == null) {
            throw new RuntimeException("无token，请重新登录");
        }
        // 获取 token 中的 user id
        Long userId;
        try {
            userId = JWT.decode(securityUser.getToken()).getClaim("userId").asLong();
            if (!securityUser.getUserId().equals(userId)) {
                throw new RuntimeException("401");
            }
        } catch (JWTDecodeException j) {
            throw new RuntimeException("401");
        }
        List<SecurityUser> securityUsers = securityUserService.selectSecurityUserList(securityUser);
        SecurityUser securityUser1 = securityUsers.stream().findFirst().orElse(null);
        if (securityUser1 == null) {
            throw new RuntimeException("用户不存在，请重新登录");
        }
        //需要判断客户端传入的过期时间是否在当前时间之后,如果不在之后需要提示用户
        Date nowDate = new Date(System.currentTimeMillis());
        if(!DateUtil.isLater(nowDate, securityUser1.getExpireTime())) {
            throw new RuntimeException("过期时间应该在当前时间之后");
        }
        // 验证 token
        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(securityUser.getChannel())).build();
        try {
            jwtVerifier.verify(securityUser.getToken());
        } catch (JWTVerificationException e) {
            throw new RuntimeException("401");
        }
        return 1;
    }

    /**
     * 修改用户
     *
     * @param securityUser 用户
     * @return 结果
     */
    @Override
    public int updateSecurityUser(SecurityUser securityUser)
    {
        return securityUserMapper.updateSecurityUser(securityUser);
    }

    /**
     * 批量删除用户
     *
     * @param ids 需要删除的用户主键
     * @return 结果
     */
    @Override
    public int deleteSecurityUserByIds(Long[] ids)
    {
        return securityUserMapper.deleteSecurityUserByIds(ids);
    }

    /**
     * 删除用户信息
     *
     * @param id 用户主键
     * @return 结果
     */
    @Override
    public int deleteSecurityUserById(Long id)
    {
        return securityUserMapper.deleteSecurityUserById(id);
    }

    @Override
    public String generateSecurityUser(SecurityUser securityUser) {
        //判断是否存在,存在则获取
        List<SecurityUser> securityUserList = securityUserService.selectSecurityUserList(securityUser);
        SecurityUser securityUser1 = securityUserList.stream().findFirst().orElse(null);
        String token = "";
        if (securityUser1 == null) {
            token= JWT.create()
                    .withClaim("userId",securityUser.getUserId())
                    .sign(Algorithm.HMAC256(securityUser.getChannel()));// 以 channel 作为 token 的密钥
            securityUser.setToken(token);
            Date expireDate = new Date("2024/12/12 12:12:00");
            securityUser.setExpireTime(expireDate);
            insertSecurityUser(securityUser);
        }else {
            token = securityUser1.getToken();
        }
        return token;
    }

    @Override
    public String generateSecurityUserV1(String encryptString, String channelId) throws Exception {
        String resultString = "";
        JSONObject jsonObject = new JSONObject();
        String aesKey = fetchAESKey(channelId);
        if (StringUtils.isNotEmpty(aesKey)) {
            //解密密文
            String decryptString = CryptoUtils.decryptSymmetrically(aesKey, null, encryptString, CryptoUtils.Algorithm.Encryption.AES_ECB_PKCS5);
            System.out.println("decryptString = " + decryptString);
            JSONObject jsonObject1 = JSON.parseObject(decryptString);
            SecurityUser securityUser = SecurityUser.builder().userId(jsonObject1.getLong("userId")).channel(jsonObject1.getString("channel")).build();
            String token = generateSecurityUser(securityUser);
            System.out.println("token = " + token);
            //加密token
            JSONObject resultJsonObject = new JSONObject();
            JSONObject tokenObject= new JSONObject();
            tokenObject.put("token", token);
            jsonObject.put("data", tokenObject);
            String responseString = JSON.toJSONString(jsonObject1);
            String encryptText = CryptoUtils.encryptSymmetrically(aesKey, null, responseString, CryptoUtils.Algorithm.Encryption.AES_ECB_PKCS5);
            resultString = encryptText;
        }

        return resultString;
    }

    /**
     * 根据channelId获取AES密钥
     * @param channelId
     * @return
     */
    private String fetchAESKey(String channelId) {
        SecurityKeyInfo aesKeyInfoQuery = SecurityKeyInfo.builder().channelId(channelId).type(3).build();
        List<SecurityKeyInfo> securityAESKeyInfoList = securityKeyInfoMapper.selectSecurityKeyInfoList(aesKeyInfoQuery);
        SecurityKeyInfo securityKeyInfo = securityAESKeyInfoList.stream().findFirst().orElse(new SecurityKeyInfo());
        return securityKeyInfo.getContent();
    }
}
